/*
    Asignatura: Procesadores de lenguajes.
    Practica de labotario numero 8.
    Autores:
                Guillermo Garcia Juanes (Alu3889)
                Jose Antonio Hernandez Gonzalez (Alu3809)

    Fichero: AnasinC.g
    Contenido: Resolucion del ejercio cuarto de la practica (SINTACTICO).
*/
parser grammar AnasinC;

options {
    tokenVocab = AnalexC;
}

@header {
    package pl.equipo13.p8;
}

/*----------------------------------------------------SINTACTICO----------------------------------------------------*/
entrada returns [String r =""]: f=funcion
            {System.out.println(f); r += f;}; /*Imprime la funcion reconocida, cada regla va construyendo un string que 
                                        se devuelve recursivamente.*/

/*Cabecera de las funciones, ej: void main(void)*/
funcion returns [String r =""]: td=tipo_dato i=IDENT ap=APARENTESIS v=VOID cp=CPARENTESIS b=bloque
                                    { r += td + " " + i.getText() + ap.getText() + v.getText() + cp.getText() + " " + b;};

/*Bloque para las funciones, condicionales o bucles, ej: { printf("punto medio %d\n",a); a=a+1; }*/
bloque returns [String r =""]: al=ALLAVE 
                               {r += al.getText() + "\n";}
                               (i=instruccion
                               {r += i;})* 
                               cl=CLLAVE
                               {r += cl.getText();};

/*Tipos de instrucciones posibles, if, llamadas a funcione, una asignacion o declaracion de una variable*/
instruccion returns [String r =""]: c=condicional {r += c + "\n";}
                                  | 
                                    l=llamada {r += l + "\n";}
                                  |
                                    a=asignacion {r += a + "\n";}
                                  |
                                    d=declaracion {r += d + "\n";};

/*Regla para los condicionales, permite tanto un if con una sola instruccion y sin llaves como una con varias y por lo tanto
llaves, ej:  if(exp) bloque */
condicional returns [String r =""]: i=IF ap=APARENTESIS ep=exp cp=CPARENTESIS 
                                        {r += i.getText() + ap.getText() + ep + cp.getText() + " ";}
                                    (b=bloque 
                                        {r += b;}
                                  | 
                                    ins=instruccion
                                        {r += ins;}
                                    );

/*Regla para las llamadas a funciones, ej: printf(argumentos);*/
llamada returns [String r =""]: id=IDENT ap=APARENTESIS ar=argumentos cp=CPARENTESIS s=SEPARADOR
                                    {r += id.getText() + ap.getText() + ar + cp.getText() + s.getText();};

/*Regla para los argumentos que se le pasan a una funcio, ej: "punto medio %d\n",a */
argumentos returns [String r =""]: (v=variable {r += v;}| c=CADENA {r += c.getText();})? 
                                        (cm=COMA (v=variable {r += cm.getText() + v;} | CADENA {r += cm.getText() + c.getText();}))*;

/*Asignaciones a una variable, ej: a=exp;*/
asignacion returns [String r =""]: id=IDENT ig=IGUAL ep=exp s=SEPARADOR
                                        {r += id.getText() + ig.getText() + ep + s.getText();};

/*Declaracion de variables, ej: int a, b;*/
declaracion returns [String r =""]: td=tipo_dato id=IDENT
                                        {r += td + " " + id.getText();}
                                    (c=COMA i=IDENT 
                                        {r += c.getText() + " " +i.getText();})*
                                    s=SEPARADOR 
                                        {r += s.getText();};

/*Tipos de datos permitidos*/
tipo_dato returns [String r =""]: td=(VOID | INT | CHAR | FLOAT)
                                  {r += td.getText();}; 

/*Reglas para todo tipo de expresiones numericas, ej: a>=2 o (2+4)*3*/
exp returns [String r =""]: (n=NEGADO {r += n.getText();}| cs=CAMBIOSIGNO {r += cs.getText();})? 
                            es=exp_sr
                            {r += es;}
                            (op=OPERADORCOMPARAR es=exp_sr {r += op.getText() + es;})?;

exp_sr returns [String r =""]: em=exp_mult
                               {r += em;} 
                               (op=OPERADORSUMRES em=exp_mult {r += op.getText() + em;})*;

exp_mult returns [String r =""]: eb=exp_base
                                 {r += eb; }
                                 (op=OPERADORMULDIV eb=exp_base {r += op.getText() + eb;})*;

exp_base returns [String r =""]: var=variable 
                                 { r+= var; } 
                               | 
                                 ap=APARENTESIS eb=exp_base cp=CPARENTESIS
                                 {r += ap.getText() + eb + cp.getText();};

/*Tipo de variables para las expresiones, tanto numeros como IDENT para el caso de tratar con variables*/
variable returns [String r =""]: var=(IDENT | NUMERO)
                                 {r += var.getText();};